package com.yzcrm.erp.kms.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Aop;
import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.yzcrm.common.config.exception.YzcrmException;
import com.yzcrm.common.config.paragetter.BasePageRequest;
import com.yzcrm.common.constant.BaseConstant;
import com.yzcrm.common.lucene.LuceneIndex;
import com.yzcrm.erp.admin.entity.AdminField;
import com.yzcrm.erp.admin.entity.AdminScene;
import com.yzcrm.erp.admin.service.AdminFieldService;
import com.yzcrm.erp.admin.service.AdminSceneService;
import com.yzcrm.erp.admin.service.AdminUserService;
import com.yzcrm.erp.crm.common.CrmEnum;
import com.yzcrm.erp.crm.service.CrmRecordService;
import com.yzcrm.erp.kms.common.KmsEnum;
import com.yzcrm.erp.kms.entity.*;
import com.yzcrm.utils.*;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiang.xue
 */
public class KmsCourseService {

    @Inject
    private CrmRecordService crmRecordService;

    @Inject
    private AdminFieldService adminFieldService;

    @Inject
    private AdminSceneService adminSceneService;

    @Inject
    private LuceneIndex luceneIndex;

    /**
     * 追加课程
     * @param jsonObject
     * @return
     */
    @Before(Tx.class)
    public R addOrUpdate(JSONObject jsonObject) {

//        Log.getLog(KmsCourseService.class).info(jsonObject.toString() + "....");

        KmsCourse kmsCourse = jsonObject.getObject("entity", KmsCourse.class);
        if(ObjectUtil.isNull(kmsCourse)) {
            R.error("参数不正确");
        }
//        Log.getLog(KmsCourseService.class).info(kmsCourse + "....");

        // 课程下的资源
        JSONArray jsonArrayResources = jsonObject.getJSONArray("resources");
        if (ObjectUtil.isNull(jsonArrayResources) || jsonArrayResources.size() == 0) {
            return R.error("请为该课程添加资源");
        }

        String batchId = StrUtil.isNotEmpty(kmsCourse.getBatchId()) ? kmsCourse.getBatchId() : IdUtil.simpleUUID();
        if(kmsCourse.getCourseId() != null){
            crmRecordService.updateRecord(jsonObject.getJSONArray("field"), batchId);
        }
        adminFieldService.save(jsonObject.getJSONArray("field"), batchId);
        boolean flag;
        if(kmsCourse.getCourseId() != null){
            // 更新

            // 课程暂时不用审核
            kmsCourse.setCheckStatus(1);
            KmsCourse oldKmsCourse = new KmsCourse().dao().findById(kmsCourse.getCourseId());
            crmRecordService.updateRecord(oldKmsCourse, kmsCourse, CrmEnum.KMS_COURSE);
            kmsCourse.setUpdateTime(DateUtil.date());
            kmsCourse.setUpdateUserId(BaseUtil.getUser().getUserId());
            flag = kmsCourse.update();

            // 增加课程下的资源
            // 删除后重新加入
            Integer count = Db.update(Db.getSql("kms.course.deleteRsourceByCourseId"), kmsCourse.getCourseId());
            if (count <= 0) {
                throw new YzcrmException("课程资源添加失败，请刷新页面重新尝试操作");
            }

            // 增加新资源文件
            for (int i = 0; i < jsonArrayResources.size(); i++) {

                JSONObject jsonObjectProduct = jsonArrayResources.getJSONObject(i);
                KmsCourseResource kmsCourseResource = jsonObjectProduct.toJavaObject(KmsCourseResource.class);

                kmsCourseResource.setId(null);
                kmsCourseResource.setCourseId(kmsCourse.getCourseId());
                kmsCourseResource.setStatus(1);
                kmsCourseResource.setCreateTime(DateUtil.date());
                kmsCourseResource.setCreateUserId(BaseUtil.getUser().getUserId());
                kmsCourseResource.setUpdateTime(DateUtil.date());
                boolean result = kmsCourseResource.save();
                if(!result) {
                    throw new YzcrmException("资源下的文件保存失败");
                }
            }

            // 更新索引
            luceneIndex.updateContent(BaseConstant.LUCENE_PATH_COURSE, CrmEnum.KMS_COURSE.getType()+"", kmsCourse.getCourseId().toString(), kmsCourse.getTitle(), kmsCourse.getRemarks());

        }else{
            // 增加

            kmsCourse.setCreateTime(DateUtil.date());
            kmsCourse.setUpdateTime(DateUtil.date());
            kmsCourse.setCreateUserId(BaseUtil.getUser().getUserId());
            kmsCourse.setBatchId(batchId);
            kmsCourse.setCheckStatus(1);// 课程暂时不用审核
            kmsCourse.setStatus(1);
            kmsCourse.setOwnerUserId(BaseUtil.getUser().getUserId());
            flag = kmsCourse.save();
            crmRecordService.addRecord(kmsCourse.getCourseId().intValue(), CrmEnum.KMS_COURSE);

            // 增加新资源文件
            for (int i = 0; i < jsonArrayResources.size(); i++) {

                JSONObject jsonObjectProduct = jsonArrayResources.getJSONObject(i);
                KmsCourseResource kmsCourseResource = jsonObjectProduct.toJavaObject(KmsCourseResource.class);

                kmsCourseResource.setId(null);
                kmsCourseResource.setCourseId(kmsCourse.getCourseId());
                kmsCourseResource.setStatus(1);
                kmsCourseResource.setCreateTime(DateUtil.date());
                kmsCourseResource.setCreateUserId(BaseUtil.getUser().getUserId());
                kmsCourseResource.setUpdateTime(DateUtil.date());
                boolean result = kmsCourseResource.save();
                if(!result) {
                    throw new YzcrmException("资源下的文件保存失败");
                }
            }

            // 创建索引
            luceneIndex.addContent(BaseConstant.LUCENE_PATH_COURSE, CrmEnum.KMS_COURSE.getType()+"", kmsCourse.getCourseId().toString(), kmsCourse.getTitle(), kmsCourse.getRemarks());

        }

        return flag ? R.ok().put("data", Kv.by("course_id", kmsCourse.getCourseId()).set("remarks", kmsCourse.getRemarks())) : R.error();
    }

    /**
     * 获取场景 并 获取课程列表
     * @param basePageRequest
     * @return
     */
    public R filterConditionAndGetPageList(BasePageRequest basePageRequest){

        JSONObject jsonObject = basePageRequest.getJsonObject();
        Integer sceneId = jsonObject.getInteger("sceneId");
        JSONObject data = new JSONObject();
        if(sceneId != null && sceneId != 0){
            data = JSON.parseObject(AdminScene.dao.findById(sceneId).getData());
        }
        if(sceneId == null && jsonObject.getInteger("type") == 1){
            data = new JSONObject().fluentPut("is_transform", new JSONObject().fluentPut("name", "is_transform").fluentPut("condition", "is").fluentPut("value", "0"));
        }
        if(jsonObject.getJSONObject("data") != null){
            if(data != null){
                data.putAll(jsonObject.getJSONObject("data"));
            }
        }
        jsonObject.put("data",data);
        basePageRequest.setJsonObject(jsonObject);
        return getCoursePageList(basePageRequest);
    }

    /**
     * 获取课程列表
     * @param basePageRequest
     * @return
     */
    public R getCoursePageList(BasePageRequest basePageRequest) {

        JSONObject jsonObject = basePageRequest.getJsonObject();
        Kv kv = new Kv();
        List<JSONObject> queryList = new ArrayList<>();
        Integer type = jsonObject.getInteger("type");
        boolean isValid = jsonObject.getBoolean("isValid") != null ? jsonObject.getBoolean("isValid") : false;

        //自定义字段列表
        Map<String, AdminField> fieldMap = adminSceneService.getAdminFieldMap(type);

        // 取得场景名称 同label
        String realm = CrmEnum.parse(type).getName();
        if(ObjectUtil.isNull(realm)) {
            return R.error("type不符合要求");
        }

        // 附加检索条件
        JSONObject data = basePageRequest.getJsonObject().getJSONObject("data");
        if (!adminSceneService.appendSqlCondition(kv, fieldMap, queryList, data, type)){
            return R.error("参数包含非法字段");
        }
        String search = basePageRequest.getJsonObject().getString("search");
        if(StrUtil.isNotEmpty(search)){
            if (!adminSceneService.appendSqlSearch(type, queryList, search)){
                return R.error("参数包含非法字段");
            }
            if(!kv.containsKey("fixed")){
                kv.set("fixed",true);
            }
        }

        // 获取排序字段
        String camelField = basePageRequest.getJsonObject().getString("sortField");
        String sortField = StrUtil.toUnderlineCase(camelField);
        String orderNum = basePageRequest.getJsonObject().getString("order");
        if(StrUtil.isEmpty(sortField) || StrUtil.isEmpty(orderNum)){
            kv.set("orderByKey", "update_time").set("orderByType", "desc").set("fieldType", 1);
        }else{
            if(! ParamsUtil.isValid(sortField)){
                return R.error("参数包含非法字段");
            }
            orderNum = "2".equals(orderNum) ? "asc" : "desc";
            kv.set("orderByKey", sortField).set("orderByType", orderNum).set("fieldType", fieldMap.get(sortField) != null ? fieldMap.get(sortField).getFieldType() : 0);
        }

        // 开始生成条件SQL
        StringBuilder conditions = new StringBuilder();

        //获取已审核数据
        if(isValid) {
            conditions.append(" and check_status = 1");
        }

        conditions.append(" and status != 2");

        // 检索权限
        Long userId = BaseUtil.getUserId();
        List<Integer> roles = BaseUtil.getUser().getRoles();
        if(! BaseConstant.SUPER_ADMIN_USER_ID.equals(userId) && !roles.contains(BaseConstant.SUPER_ADMIN_ROLE_ID)){

            String menuRealm = "course";

            List<Long> longs = Aop.get(AdminUserService.class).queryUserByAuth(userId, menuRealm);
            if(longs != null && longs.size() > 0){
                conditions.append(" and (a.owner_user_id in (").append(StrUtil.join(",", longs)).append(")");
                conditions.append(")");
            }
        }
        JSONObject sqlObject = new JSONObject();
        sqlObject.put("sql", conditions.toString());
        sqlObject.put("type", 1);
        if(!kv.containsKey("fixed")){
            kv.set("fixed",true);
        }
        queryList.add(sqlObject);

        // 设置分页
        if(StrUtil.isEmpty(basePageRequest.getJsonObject().getString("excel"))){
            kv.set("page", (basePageRequest.getPage() - 1) * basePageRequest.getLimit()).set("limit", basePageRequest.getLimit());
        }

        String selectSql = "select * ";
        List<String> batchList = adminSceneService.queryBatchId(queryList);
        if(batchList.size()==0&&kv.containsKey("field")){
            batchList.add("");
        }
        kv.set("select", selectSql).set("queryList", queryList).set("realm", realm).set("fieldMap", fieldMap).set("label", type);
        kv.set("batchList",batchList);
        SqlPara sqlPara = null;
        if(kv.getInt("fieldType") == 0){
            sqlPara = Db.getSqlPara("kms.course.queryCoursePageList2", kv);
        }else{
            sqlPara = Db.getSqlPara("kms.course.queryCoursePageList1", kv);
        }

        // 检索数据
        List<Record> recordPage = Db.find(sqlPara);

        JSONObject resultJsonObject = new JSONObject();
        resultJsonObject.put("list", recordPage);
        SqlPara countSql = Db.getSqlPara("kms.course.queryCoursePageListCount", kv);
        Integer count = Db.queryInt(countSql.getSql(), countSql.getPara());
        resultJsonObject.put("totalRow", count);
        return R.ok().put("data", resultJsonObject);

    }

    /**
     * 根据课程id查询
     */
    public Record queryById(Integer courseId){
        Record record = Db.findFirst(Db.getSql("kms.course.queryById"), courseId);
        List<Record> recordList = Db.find("select name,value from `yzcrm_admin_fieldv` where batch_id = ?", record.getStr("batch_id"));
        recordList.forEach(field -> record.set(field.getStr("name"), field.getStr("value")));
        return record;
    }

    /**
     * 查询编辑字段
     */
    public List<Record> queryField(Integer courseId){
        Record course = queryById(courseId);
        List<Record> fieldList = adminFieldService.queryUpdateField(CrmEnum.KMS_COURSE.getType(), course);
        return fieldList;
    }

    /**
     * 根据id删除课程
     */
    public R deleteByIds(String customerIds){
        String[] idsArr = customerIds.split(",");
        List<Record> idsList = new ArrayList<>();
        for(String id : idsArr){
            String permissions = "kms:course:delete";
            if(!BaseUtil.getUserId().equals(BaseConstant.SUPER_ADMIN_USER_ID) && !BaseUtil.getUser().getRoles().contains(BaseConstant.SUPER_ADMIN_ROLE_ID)
                    && !AuthUtil.isHavaAuth(permissions)
                    && Db.queryInt(Db.getSql("kms.course.queryIsOwnerUser"), BaseUtil.getUserId(), id) <= 0){
                return R.error("没有权限");
            }
            Record record = new Record();
            idsList.add(record.set("course_id", Integer.valueOf(id)));
        }

        List<Record> batchIdList = Db.find(Db.getSqlPara("kms.course.queryBatchIdByIds", Kv.by("ids", idsArr)));
        boolean result = Db.tx(() -> {
            Db.batch(Db.getSql("kms.course.deleteByIds"), "course_id", idsList, 100);
//            Db.batch("delete from yzcrm_admin_fieldv where batch_id = ?", "batch_id", batchIdList, 100);
            return true;
        });

        if(result == true) {

            for(String id : idsArr) {
                // 删除索引
                luceneIndex.deleteContent(BaseConstant.LUCENE_PATH_COURSE, id);
            }
        }

        return result ? R.ok() : R.error();
    }

    /**
     * 基本信息
     */
    public List<Record> information(Integer courseId) {
        Record record = queryById(courseId);
        List<String> keyList = Arrays.asList("title", "remarks");
        List<Record> recordList = adminFieldService.queryInformation(CrmEnum.KMS_COURSE, record, keyList);
        return recordList.stream().sorted(Comparator.comparingInt(r->-r.getInt("field_type"))).map(r-> r.remove("field_type","field_name","setting","type")).collect(Collectors.toList());
    }

    /**
     * 根据课程ID获取课程下的资源
     * @param courseId
     * @return
     */
    public List<Record> listResourcesByCourseId(Integer courseId) {

        // 根据课程ID获取课程下的资源
        List<Record> listCourseResources = Db.find(Db.getSql("kms.course.queryResourcesByCourseId"), courseId);

        return listCourseResources;
    }


    /**
     * 获取手机端课程列表
     */
    public R getUserCourseList(Integer page, Integer limit, List<Integer> roles, Long userId, String courseName) {

        if(ObjectUtil.isNotNull(page) && ObjectUtil.isNotNull(limit)) {
            page = (page-1)*limit;
        }

        Kv kv = new Kv();

        // 检索用户拥有的角色
//        List<Integer> roles = BaseUtil.getUser().getRoles();
        if(ObjectUtil.isNotNull(roles) && roles.size() > 0) {

            kv.set("roles", roles);
            kv.set("page", page);
            kv.set("limit", limit);
            kv.set("userId", userId);
            kv.set("courseName", courseName);


            // 检索数据
            SqlPara sqlPara = Db.getSqlPara("kms.course.queryUserCourseList", kv);
            List<Record> recordPage = Db.find(sqlPara);
            // 总数
            SqlPara countSql = Db.getSqlPara("kms.course.queryUserCourseListCount", kv);
            Integer count = Db.queryInt(countSql.getSql(), countSql.getPara());

            // 所有课程学时及学习时间
            Kv kv2 = new Kv();
            kv2.set("roles", roles);
            kv2.set("userId", userId);
            kv2.set("courseName", courseName);
            SqlPara sqlParaStudiedInfo = Db.getSqlPara("kms.course.queryUserCourseList", kv2);
            List<Record> recordPageStudiedInfo = Db.find(sqlParaStudiedInfo);
            Integer[] courseSeconds = {0};
            Integer[] studiedSeconds = {0};
            recordPageStudiedInfo.forEach(record -> {

                courseSeconds[0] = courseSeconds[0] + record.getInt("standard_study_seconds");
                studiedSeconds[0] = studiedSeconds[0] + record.getInt("studied_seconds");
            });

            // 最后一次学习时间
            SqlPara lastStudyTimeSql = Db.getSqlPara("kms.course.queryUserCourseLastStudyTime", kv);
            Date lastStudyTime = Db.queryDate(lastStudyTimeSql.getSql(), lastStudyTimeSql.getPara());

            JSONObject resultJsonObject = new JSONObject();
            resultJsonObject.put("list", recordPage);
            resultJsonObject.put("totalRow", count);
            resultJsonObject.put("allCourseSeconds", courseSeconds[0]);
            resultJsonObject.put("allCourseStudiedSeconds", studiedSeconds[0]);
            resultJsonObject.put("lastStudyTime", lastStudyTime);

            return R.ok().put("data", resultJsonObject);
        } else {

            JSONObject resultJsonObject = new JSONObject();
            resultJsonObject.put("list", new ArrayList<Record>());
            resultJsonObject.put("totalRow", 0);
            resultJsonObject.put("courseSeconds", 0);
            resultJsonObject.put("studiedSeconds", 0);
            resultJsonObject.put("lastStudyTime", 0);

            return R.ok().put("data", resultJsonObject);
        }

    }

    /**
     * 课程中的文件学习中，更新文件学习记录
     */
    public void updateUserFileStudiedLog(Long userId, Integer courseId, Integer fileId, Integer studiedSeconds, Integer studiedToSeconds) {

        KmsCourse course = KmsCourse.dao.findFirst("select * from yzcrm_kms_course where course_id=? and status=1 ", courseId);
        if(ObjectUtil.isNull(course)) {
            return;
        }


        KmsFile file = KmsFile.dao.findFirst("select * from yzcrm_kms_file where file_id=? and status=1 ", fileId);
        if(ObjectUtil.isNull(file)) {
            return;
        }

        // 检索用户拥有的角色
        boolean isOwener = false;
        List<Integer> roles = BaseUtil.getUser().getRoles();
        for (int i = 0; i < roles.size(); i++) {
            String roleId = String.valueOf(roles.get(i));

            String[] arr = course.getRoleId().split(",");
            List<String> list = Arrays.asList(arr);
            if(list.contains(roleId)) {

                isOwener = true;
                break;
            }
        }
        if (!isOwener) {
            return;
        }


        // 检索学习记录
        KmsUserFile userFile = KmsUserFile.dao.findFirst("select * from yzcrm_kms_user_file where user_id=? and course_id=? and file_id=? and status=1 order by id", userId, courseId, fileId);
        if (ObjectUtil.isNull(userFile)) {

            String batchId = "";

            // 不同课程中同一文件学习记录共享
            userFile = KmsUserFile.dao.findFirst("" +
                            "select * from yzcrm_kms_user_file " +
                            "where user_id=? and file_id=? and status=1 " +
                            "order by update_time desc ",
                    userId,  fileId);
            int days = 30; // 最大共享天数
            if (ObjectUtil.isNotNull(userFile) &&
                    (int) ((new Date().getTime() - userFile.getUpdateTime().getTime()) / 1000 / 60 / 60 / 24) < days
                    ) {
                // 共享学习记录 batch_id，一个月内学习的内容共享

                batchId = userFile.getBatchId();
            } else {

                batchId =  IdUtil.simpleUUID();
            }

            userFile = new KmsUserFile();
            userFile.setUserId(userId);
            userFile.setCourseId(Long.valueOf(courseId));
            userFile.setFileId(Long.valueOf(fileId));
            userFile.setBatchId(batchId);
            userFile.setCreateTime(DateUtil.date());
            userFile.setUpdateTime(DateUtil.date());
            userFile.setCreateUserId(BaseUtil.getUser().getUserId());
            userFile.setStatus(1);
            userFile.setStudiedToSeconds(studiedToSeconds);
            userFile.setStudyStatus(KmsEnum.STUDY_STATUS_STUDYING.getType());
            userFile.save();

        } else {


        }

        // 学习完成状态判断
        int studyStatus = userFile.getStudyStatus();
        if(ObjectUtil.isNotNull(studiedToSeconds) && studyStatus!=KmsEnum.STUDY_STATUS_COMPLETE.getType() && (Math.abs(file.getStandardStudySeconds()-studiedToSeconds) <= 5 || studiedToSeconds >= file.getStandardStudySeconds())) {
            studyStatus = KmsEnum.STUDY_STATUS_COMPLETE.getType();
        }

        // 如果是文件，打开即学完处理
        try {

            URL url = new URL(file.getPath());

            String objectName = url.getPath();
            String fileContentType = FileUploadUtil.getContentType(objectName);
            if(!fileContentType.contains("video") && !fileContentType.contains("octet-stream")) {
                studyStatus = KmsEnum.STUDY_STATUS_COMPLETE.getType();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }


        // 同一batch_id的学习状态更新， 学习中 或者 学习完成
        userFile.setUpdateTime(DateUtil.date());
        userFile.setUpdateUserId(BaseUtil.getUser().getUserId());
        userFile.setStudiedToSeconds(studiedToSeconds);
        userFile.setStudyStatus(studyStatus);
        userFile.update();


        // 增加学习记录
        KmsStudyLog studyLog = new KmsStudyLog();
        studyLog.setBatchId(userFile.getBatchId());
        studyLog.setStudiedToSeconds(studiedToSeconds);
        studyLog.setStudiedSeconds(studiedSeconds);
        studyLog.setStatus(1);
        studyLog.setCreateTime(DateUtil.date());
        studyLog.setUpdateTime(DateUtil.date());
        studyLog.setCreateUserId(BaseUtil.getUser().getUserId());
        studyLog.save();

    }



    /**
     * 获取课程中的文件最后一次学习到的秒数
     */
    public R queryCourseFileLastStudiedToSeconds(Integer courseId, Integer fileId, Long userId) {


        Integer studiedToSeconds = Db.queryInt("select studied_to_seconds from yzcrm_kms_user_file " +
                "where course_id = ? and file_id = ? and user_id = ? and status=1 ",courseId,fileId,userId);

        JSONObject resultJsonObject = new JSONObject();
        resultJsonObject.put("studiedToSeconds", ObjectUtil.isNull(studiedToSeconds)?0:studiedToSeconds);

        return R.ok().put("data", resultJsonObject);

    }

}
